<?php
# ***** BEGIN LICENSE BLOCK *****
# This file is part of "myWiWall".
# Copyright (c) 2007-2008 CRP Henri Tudor and contributors.
# All rights reserved.
#
# "myWiWall" is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
# 
# "myWiWall" is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with "myWiWall"; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# ***** END LICENSE BLOCK *****
abstract class AbstractHttpProxy
{
	const METHOD_GET 		= 'GET';
	const METHOD_POST 		= 'POST';
	const METHOD_PUT 		= 'PUT';
	const METHOD_DELETE 	= 'DELETE';
	const METHOD_HEAD 		= 'HEAD';
	
	const VERSION_10		= 'HTTP/1.0';
	const VERSION_11		= 'HTTP/1.1';
	
	protected $requestMethod;
	protected $requestHost;
	protected $requestPort;
	protected $requestPath;
	protected $requestVersion;
	protected $requestTimeout;
	protected $requestHeaders = array();
	protected $requestBody = '';
	protected $responseHeaders = array();
	protected $responseBody = '';
	protected $parameters = array();
	protected $relayedHeaders = array();
	protected $useHttps = false;
	protected $responseHttpStatus = '';
	
	public function __construct($requestMethod, $requestHost, $requestPort = 80, $requestPath = '/', $requestVersion = self::VERSION_11, $requestTimeout = 0)
	{
		// construction checks.
		$this->checkMethod($requestMethod);
		$this->checkHost($requestHost);
		$this->checkPort($requestPort);
		$this->checkPath($requestPath);
		$this->checkVersion($requestVersion);
		$this->checkTimeout($requestTimeout);
		
		$this->requestMethod = $requestMethod;
		$this->requestHost = $requestHost;
		$this->requestPort = $requestPort;
		$this->requestPath = $requestPath;
		$this->requestVersion = $requestVersion;
		$this->requestTimeout = $requestTimeout;
	}
	
	public function useHttps($useHttps)
	{
		$this->useHttps = $useHttps;
	}
	
	public function performRequest()
	{
		$this->connect();
		$this->handleRequestResponse();
		$this->disconnect();
	}
	
	public function sendResponse()
	{
		foreach ($this->responseHeaders as $fieldName => $fieldValue)
			header($fieldName . ': ' . $fieldValue, true, $this->responseHttpStatus);
		
		echo $this->responseBody;
	}
	
	public function setRequestHeader($fieldName, $fieldValue)
	{
		$key = trim(strtolower($fieldName));
		$this->requestHeaders[$key] = $fieldValue;
	}
	
	public function setResponseHeader($fieldName, $fieldValue)
	{
		$key = trim(strtolower($fieldName));
		$this->responseHeaders[$key] = $fieldValue;
	}
	
	public function setRequestBody($body)
	{
		if ($this->requestMethod == self::METHOD_POST || $this->requestMethod == self::METHOD_PUT)
			$this->setRequestHeader('Content-length', strlen($body));
	
		$this->requestBody = $body;
	}
	
	public function setParameter($name, $value, $needEncode = true)
	{
		array_push($this->parameters, array('name' => ($needEncode) ? urlencode($name) : $name, 'value' => ($needEncode) ? urlencode($value) : $value));
	}
	
	public function setParameters(array $parameters, $needEncode = true)
	{
		if (!$needEncode)
		{
			$this->parameters = array_merge($this->parameters, $parameters);
		}
		else
		{
			$encodedParameters = array();
			foreach ($parameters as $param)
				$encodedParameters[] = array('name' => urlencode($param['name']), 'value' => urlencode($param['value']));
				
			$this->parameters = $encodedParameters;
		}
	}
		
	public function setRelayedHeaders(array $headerNames)
	{
		$cleanNames = array();
		foreach($headerNames as $headerName)
			$cleanNames[] = strtolower($headerName);
		
		$this->relayedHeaders = $cleanNames;
	}
	
	protected function setResponseBody($body)
	{
		$this->responseBody = $body;
	}
	
	protected function checkPath($path)
	{
		if (!is_string($path) || $path == '')
			throw new HttpProxyException("The request path '${path}' is not valid.", HttpProxyException::BAD_PATH);
	}
	
	protected function checkTimeout($timeout)
	{
		if (!is_int($timeout) || $timeout < 0)
			throw new HttpProxyException("The request timeout value '${timeout}' is not valid.", HttpProxyException::BAD_TIMEOUT);
	}
	
	protected function checkHost($host)
	{
		if (!is_string($host) && $host == '')
			throw new HttpProxyException("The request host '${host}' is not valid.", HttpProxyException::BAD_HOST);
	}
	
	protected function checkPort($port)
	{
		if (!is_int($port))
			throw new HttpProxyException("The request port '${port}' is not valid.");
	}
	
	protected abstract function checkMethod($method);
	protected abstract function checkVersion($version);
	protected abstract function connect();
	protected abstract function disconnect();
	protected abstract function handleRequestResponse();
}
?>